在现在,绝大多数软件都向着简洁,时尚发展。就拿有道的单词本和我做的单词本来说,绝大多数用户肯定喜欢我所做的单词本(就单单界面,关于颜色搭配和布局问题,大家就不要在意了)。
有道的单词本:
我所做的单词本:
很明显,两者的主要区别就是周围的边框问题。你可以对比QQ以前的版本和这几年的版本,就会发现都倾向于下面这种窗口模式。下面我们就说说如何用Qt实现无边框窗口的缩放与拖动。
对于无边框窗口的拖动其实很简单,其基本思想是,在鼠标移动前后记录鼠标的坐标,然后将窗口移动这两个坐标之差的距离即可,具体实现可以看代码,就非常清楚了。下面主要讲讲如何实现鼠标改变窗口的大小,首先,我们将一个窗口分为以下9个区域,其中只有鼠标在22区域时无法改变其形状,不能改变窗口大小。当鼠标在其它区域时,鼠标改变形状并可以改变窗口大小。窗口区域分类如下图:
具体实现如下代码(widget.ui未做任何改变):
1、widget.h文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #ifndef WIDGET_H #define WIDGET_H
#include <QWidget> #define MARGIN 20 namespace Ui { class Widget; }
class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); int countFlag(QPoint p, int row); void setCursorType(int flag); int countRow(QPoint p);
protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); private: Ui::Widget *ui; bool isLeftPressed; int curPos; QPoint pLast; };
#endif
|
2、widget.cpp文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| #include "widget.h" #include "ui_widget.h" #include<QMouseEvent> #include<QDebug>
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); this->setMouseTracking(true); isLeftPressed=false; curPos=0; this->setMinimumSize(400,300); QCursor cursor; cursor.setShape(Qt::ArrowCursor); QWidget::setCursor(cursor); qDebug()<<"h="<<this->height(); setWindowFlags(Qt::FramelessWindowHint); qDebug()<<this->minimumHeight(); }
Widget::~Widget() { delete ui; } void Widget::mousePressEvent(QMouseEvent *event) { if(event->button()==Qt::LeftButton) { this->isLeftPressed=true; QPoint temp=event->globalPos(); pLast=temp; curPos=countFlag(event->pos(),countRow(event->pos())); event->ignore(); } }
void Widget::mouseReleaseEvent(QMouseEvent *event) { if(isLeftPressed) isLeftPressed=false; QApplication::restoreOverrideCursor(); event->ignore(); }
void Widget::mouseDoubleClickEvent(QMouseEvent *event) { if(event->button()==Qt::LeftButton) { if(windowState()!=Qt::WindowFullScreen) setWindowState(Qt::WindowFullScreen); else setWindowState(Qt::WindowNoState); } event->ignore(); }
void Widget::mouseMoveEvent(QMouseEvent *event) {
int poss=countFlag(event->pos(),countRow(event->pos())); setCursorType(poss); if(isLeftPressed) { QPoint ptemp=event->globalPos(); ptemp=ptemp-pLast; if(curPos==22) { ptemp=ptemp+pos(); move(ptemp); } else { QRect wid=geometry();
switch(curPos) {
case 11:wid.setTopLeft(wid.topLeft()+ptemp);break; case 13:wid.setTopRight(wid.topRight()+ptemp);break; case 31:wid.setBottomLeft(wid.bottomLeft()+ptemp);break; case 33:wid.setBottomRight(wid.bottomRight()+ptemp);break; case 12:wid.setTop(wid.top()+ptemp.y());break; case 21:wid.setLeft(wid.left()+ptemp.x());break; case 23:wid.setRight(wid.right()+ptemp.x());break; case 32:wid.setBottom(wid.bottom()+ptemp.y());break; } setGeometry(wid); }
pLast=event->globalPos(); } event->ignore(); }
int Widget::countFlag(QPoint p,int row) { if(p.y()<MARGIN) return 10+row; else if(p.y()>this->height()-MARGIN) return 30+row; else return 20+row; }
void Widget::setCursorType(int flag) { Qt::CursorShape cursor; switch(flag) { case 11: case 33: cursor=Qt::SizeFDiagCursor;break; case 13: case 31: cursor=Qt::SizeBDiagCursor;break; case 21: case 23: cursor=Qt::SizeHorCursor;break; case 12: case 32: cursor=Qt::SizeVerCursor;break; case 22: cursor=Qt::OpenHandCursor;break; default: break;
} setCursor(cursor); }
int Widget::countRow(QPoint p) { return (p.x()<MARGIN)?1:(p.x()>(this->width()-MARGIN)?3:2); }
|
3、main.cpp文件
1 2 3 4 5 6 7 8 9 10
| #include<QtWidgets> #include "widget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
|
程序运行截图如下:
当你将鼠标放在窗口的边缘时,鼠标会变化形状,表示可以拖动窗口。由于没有关闭窗口,只能在强制关闭窗口。如果想做到和不同窗口实现最小化和关闭窗口的画,我们可以在窗口左上角放置两个ToolButton,并设置autorise属性,加上图片即可。下面给出使用上面的无边框窗口所做的词典软件的主界面:
基于Qt的词典开发系列
- 词典框架设计及成品展示
- 本地词典的设计
- 开始菜单的设计
- 无边框窗口的缩放与拖动
- 无边框窗口的拖动
- 界面美化设计
- 调用网络API
- 用户登录及API调用的实现
- JSON数据解析
- 国际音标的显示
- 系统托盘的显示
- 调用讲述人
- 音频播放
- 自动补全功能
- HTML特殊字符及正则表达式
- 后序
作品下载地址(发布版):http://download.csdn.net/detail/tengweitw/8548767
作品下载地址(绿色版):http://download.csdn.net/detail/tengweitw/8830495
源码下载地址:http://download.csdn.net/detail/tengweitw/8830503